package com.kamenrider.adventureaffiliated.procedures;

import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.common.MinecraftForge;

import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.util.Mth;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.particles.ParticleTypes;

import javax.annotation.Nullable;

import java.util.stream.Collectors;
import java.util.Random;
import java.util.List;
import java.util.Comparator;

import com.kamenrider.adventureaffiliated.init.RiderAdventureAffiliatedModEntities;
import com.kamenrider.adventureaffiliated.entity.BasketballeffectsEntity;
import com.kamenrider.adventureaffiliated.entity.AnotherBuild2019Entity;
import com.kamenrider.adventureaffiliated.entity.AnotherBuild2017Entity;

@Mod.EventBusSubscriber
public class AnotherBuildAttackEventProcedure {
	@SubscribeEvent
	public static void onEntitySetsAttackTarget(LivingSetAttackTargetEvent event) {
		execute(event, event.getEntityLiving().level, event.getEntityLiving().getX(), event.getEntityLiving().getY(), event.getEntityLiving().getZ(), event.getTarget(), event.getEntityLiving());
	}

	public static void execute(LevelAccessor world, double x, double y, double z, Entity entity, Entity sourceentity) {
		execute(null, world, x, y, z, entity, sourceentity);
	}

	private static void execute(@Nullable Event event, LevelAccessor world, double x, double y, double z, Entity entity, Entity sourceentity) {
		if (entity == null || sourceentity == null)
			return;
		if ((ForgeRegistries.ENTITIES.getKey(sourceentity.getType()).toString()).equals("rider_adventure_affiliated:another_build_2017")
				|| (ForgeRegistries.ENTITIES.getKey(sourceentity.getType()).toString()).equals("rider_adventure_affiliated:another_build_2019")) {
			if (Mth.nextInt(new Random(), 1, 10) == 3) {
				if (sourceentity.getPersistentData().getBoolean("basketball") == false) {
					sourceentity.getPersistentData().putBoolean("basketball", (true));
					if (world instanceof ServerLevel _level) {
						Entity entityToSpawn = new BasketballeffectsEntity(RiderAdventureAffiliatedModEntities.BASKETBALLEFFECTS.get(), _level);
						entityToSpawn.moveTo(x, (y + 1), z, world.getRandom().nextFloat() * 360F, 0);
						if (entityToSpawn instanceof Mob _mobToSpawn)
							_mobToSpawn.finalizeSpawn(_level, world.getCurrentDifficultyAt(entityToSpawn.blockPosition()), MobSpawnType.MOB_SUMMONED, null, null);
						world.addFreshEntity(entityToSpawn);
					}
					{
						final Vec3 _center = new Vec3((sourceentity.getX()), (sourceentity.getY()), (sourceentity.getZ()));
						List<Entity> _entfound = world.getEntitiesOfClass(Entity.class, new AABB(_center, _center).inflate(32 / 2d), e -> true).stream().sorted(Comparator.comparingDouble(_entcnd -> _entcnd.distanceToSqr(_center)))
								.collect(Collectors.toList());
						for (Entity entityiterator : _entfound) {
							if ((ForgeRegistries.ENTITIES.getKey(entityiterator.getType()).toString()).equals("rider_adventure_affiliated:basketballeffects")) {
								if (entityiterator instanceof Mob _entity)
									_entity.getNavigation().moveTo((entity.getX()), (entity.getY()), (entity.getZ()), 10);
								entityiterator.startRiding(entity);
							}
						}
					}
					new Object() {
						private int ticks = 0;
						private float waitTicks;
						private LevelAccessor world;

						public void start(LevelAccessor world, int waitTicks) {
							this.waitTicks = waitTicks;
							MinecraftForge.EVENT_BUS.register(this);
							this.world = world;
						}

						@SubscribeEvent
						public void tick(TickEvent.ServerTickEvent event) {
							if (event.phase == TickEvent.Phase.END) {
								this.ticks += 1;
								if (this.ticks >= this.waitTicks)
									run();
							}
						}

						private void run() {
							sourceentity.getPersistentData().putBoolean("basketball", (false));
							MinecraftForge.EVENT_BUS.unregister(this);
						}
					}.start(world, 60);
				}
			} else if (Mth.nextInt(new Random(), 1, 10) == 2) {
				if (sourceentity.getPersistentData().getBoolean("Knight_kicks") == false) {
					sourceentity.getPersistentData().putBoolean("Knight_kicks", (true));
					if (sourceentity instanceof AnotherBuild2017Entity) {
						((AnotherBuild2017Entity) sourceentity).setAnimation("best_match");
					}
					if (sourceentity instanceof AnotherBuild2019Entity) {
						((AnotherBuild2019Entity) sourceentity).setAnimation("best_match");
					}
					if (sourceentity instanceof Mob _entity)
						_entity.getNavigation().moveTo((entity.getX()), (entity.getY()), (entity.getZ()), 2);
					new Object() {
						private int ticks = 0;
						private float waitTicks;
						private LevelAccessor world;

						public void start(LevelAccessor world, int waitTicks) {
							this.waitTicks = waitTicks;
							MinecraftForge.EVENT_BUS.register(this);
							this.world = world;
						}

						@SubscribeEvent
						public void tick(TickEvent.ServerTickEvent event) {
							if (event.phase == TickEvent.Phase.END) {
								this.ticks += 1;
								if (this.ticks >= this.waitTicks)
									run();
							}
						}

						private void run() {
							if (world instanceof ServerLevel _level)
								_level.sendParticles(ParticleTypes.LAVA, (entity.getX()), (entity.getY()), (entity.getZ()), 10, 0, 0, 0, 0.1);
							if (world instanceof ServerLevel _level)
								_level.sendParticles(ParticleTypes.CAMPFIRE_COSY_SMOKE, (entity.getX()), (entity.getY()), (entity.getZ()), 10, 2, 2, 2, 5);
							MinecraftForge.EVENT_BUS.unregister(this);
						}
					}.start(world, 20);
					new Object() {
						private int ticks = 0;
						private float waitTicks;
						private LevelAccessor world;

						public void start(LevelAccessor world, int waitTicks) {
							this.waitTicks = waitTicks;
							MinecraftForge.EVENT_BUS.register(this);
							this.world = world;
						}

						@SubscribeEvent
						public void tick(TickEvent.ServerTickEvent event) {
							if (event.phase == TickEvent.Phase.END) {
								this.ticks += 1;
								if (this.ticks >= this.waitTicks)
									run();
							}
						}

						private void run() {
							if (world instanceof ServerLevel _level)
								_level.sendParticles(ParticleTypes.EXPLOSION_EMITTER, (entity.getX()), (entity.getY()), (entity.getZ()), 10, 0, 0, 0, 0.1);
							entity.hurt(DamageSource.GENERIC, 150);
							MinecraftForge.EVENT_BUS.unregister(this);
						}
					}.start(world, 40);
					new Object() {
						private int ticks = 0;
						private float waitTicks;
						private LevelAccessor world;

						public void start(LevelAccessor world, int waitTicks) {
							this.waitTicks = waitTicks;
							MinecraftForge.EVENT_BUS.register(this);
							this.world = world;
						}

						@SubscribeEvent
						public void tick(TickEvent.ServerTickEvent event) {
							if (event.phase == TickEvent.Phase.END) {
								this.ticks += 1;
								if (this.ticks >= this.waitTicks)
									run();
							}
						}

						private void run() {
							sourceentity.getPersistentData().putBoolean("Knight_kicks", (false));
							MinecraftForge.EVENT_BUS.unregister(this);
						}
					}.start(world, 200);
				}
			}
		}
	}
}
